[repo-assist] perf: string/int fast-paths in toParam; StringBuilder+String.Concat in buildXmlDoc#435
Merged
sergey-tihon merged 2 commits intoMay 14, 2026
Conversation
…Concat in buildXmlDoc - toParam: add explicit match arms for string, int32, int64, bool to skip GetType() + four type checks (two FullName comparisons, IsGenericType, IsEnum) for the most common OpenAPI scalar parameter types. - buildXmlDoc (Utils.fs): replace list-comprehension + String.concat for paramParts with a StringBuilder loop to avoid F# list cons-cell allocation; replace the final four-way string concatenation with String.Concat(a,b,c,d) to avoid two intermediate string allocations per compiled operation. All 417 unit tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Two micro-optimizations: a fast path in RuntimeHelpers.toParam for the most common scalar types (string/int32/int64/bool) to avoid reflection, and a StringBuilder/String.Concat rewrite of Utils.buildXmlDoc to reduce intermediate allocations.
Changes:
- Add fast-path match arms for
string,int32,int64,boolintoParambefore the reflective fallback. - Replace list comprehension +
String.concat ""withStringBuilderfor assembling<param>parts inbuildXmlDoc. - Replace chained
+join of XML doc parts withString.Concat4-arg overload.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/SwaggerProvider.Runtime/RuntimeHelpers.fs | Adds scalar-type fast paths in toParam matching prior semantics (uses ToString() like previous fallback). |
| src/SwaggerProvider.DesignTime/Utils.fs | Rewrites paramParts building with StringBuilder and joins final parts via String.Concat. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 This PR was created by Repo Assist, an automated AI assistant.
Summary
Two targeted performance improvements identified during routine codebase analysis.
1.
RuntimeHelpers.toParam— fast-path arms for common scalar typestoParamis called for every query parameter, path parameter, and header value in every generated API client call. Previously, all types exceptDateTimeandDateTimeOffsetfell into the catch-all_ ->branch, which:obj.GetType()ty.FullNametodateOnlyTypeNamety.FullNametotimeOnlyTypeNamety.IsGenericTypety.IsEnumobj.ToString()For the most common OpenAPI scalar types —
string,int32,int64, andbool— all five checks are wasted work.Fix: add explicit match arms for these four types, short-circuiting directly to the result:
This avoids
GetType()plus four branch evaluations per call for any parameter of these types.2.
Utils.buildXmlDoc— StringBuilder +String.Concatwith 4 argsbuildXmlDocis called once per compiled operation at design time. Two minor allocations reduced:[ for ... do yield ... ] |> String.concat ""(builds an F# cons-cell list then concatenates) with aStringBuilderloop — no intermediate list allocation.summaryPart + remarksPart + paramParts + returnsPart(two intermediate strings due to left-associative+) withString.Concat(summaryPart, remarksPart, paramParts, returnsPart)— single allocation.Test Status
✅ All 417 unit tests pass
✅ Build succeeds (0 errors, warnings pre-existing)
✅ Fantomas format check passes